package cn.seaboot.admin.user.service;

import cn.seaboot.admin.mvc.cache.CacheName;
import cn.seaboot.admin.mvc.Result;
import cn.seaboot.admin.user.bean.Role;
import cn.seaboot.admin.user.bean.UserDept;
import cn.seaboot.admin.user.context.AuthorityCache;
import cn.seaboot.admin.user.context.UserContext;
import cn.seaboot.admin.user.dao.UserDeptDao;
import cn.seaboot.commons.core.CommonUtils;
import cn.seaboot.commons.core.SmartText;
import cn.seaboot.commons.exception.BizException;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;


/**
 * 　– Parent：父节点
 * – Child：子节点
 * – Sibling：同胞节点
 * – Ancestor：先辈节点
 * – Descendant：后代节点
 *
 * @author postm
 */
@Service
public class UserDeptService {

    @Resource
    private RoleService roleService;

    @Resource
    private UserDeptDao userDeptDao;

    @Resource
    private UserContext userContext;

    @Resource
    private AuthorityCache<?, ?> authorityCache;

    /**
     * 新增用空的户组
     *
     * @param pid 父级 ID
     */

    public UserDept insert(String pid) {
        UserDept parent = userDeptDao.selectById(userContext.getOrgId(), pid);
        if (parent.getLevel() > 4) {
            throw new BizException("分组层级过大，不推荐继续添加!");
        }
        String path = this.getNextPathCode(parent);
        UserDept group = new UserDept();
        group.setId(path);
        group.setPath(path);
        group.setPid(parent.getId());

        group.setDeptName("new mode");
        group.setEditable(Boolean.TRUE);

        group.setOrgId(parent.getOrgId());
        group.setLevel(parent.getLevel() + 1);
        userDeptDao.insert(group);
        return group;
    }

    /**
     * 分组编码规则
     * <p>
     * 例如：根节点为 00，第一个子节点则为 0001，第二个子节点为 0002，
     * 依次类推，每一层最多99个节点。
     *
     * @param parent 父节点
     * @return 路径
     */
    private String getNextPathCode(UserDept parent) {
        // 获取最大的子级节点
        String path = userDeptDao.selectMaxChildrenPath(userContext.getOrgId(), parent.getId());
        if (CommonUtils.isEmpty(path)) {
            // 如果不存在子级，则定为01编号
            return parent.getPath() + "01";
        } else {
            String code = path.substring(path.length() - 2);
            int val = Integer.parseInt(code);
            if (val > 99) {
                throw new BizException("用户分组已经达到容量上限，不允许继续添加子分组");
            }
            return parent.getPath() + SmartText.fillZero(1 + val, 2);
        }
    }


    /**
     * 删除用户组
     *
     * @param id 部门ID
     * @return Result
     */

    @CacheEvict(cacheNames = CacheName.USER, key = "'sys_user_group.' + #id")
    public Result deleteById(String id) {
        authorityCache.clear();
        if (userDeptDao.selectChildrenCnt(userContext.getOrgId(), id) > 0) {
            return Result.failed("该用户组不为空，请先清空子用户组后再删除！");
        }
        if (userDeptDao.selectChildrenCnt(userContext.getOrgId(), id) > 0) {
            return Result.failed("该用户组还有用户，无法删除！");
        }
        return Result.doUpdate(userDeptDao.deleteById(userContext.getOrgId(), id));
    }

    /**
     * 更新用户组
     */

    @CacheEvict(cacheNames = CacheName.USER, key = "'sys_user_group.' + #id")
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public int updateById(String id, UserDept group) {
        authorityCache.clear();
        group.setId(id);
        return userDeptDao.updateSampleById(group);
    }

    /**
     * 查询用户组
     *
     * @param id 部门ID
     * @return pojo
     */

    public UserDept queryById(String orgId, String id) {
        return userDeptDao.selectById(orgId, id);
    }

    /**
     * 查询用户组
     *
     * @param id 部门ID
     * @return pojo
     */

    public UserDept queryById(String id) {
        return userDeptDao.selectById(userContext.getOrgId(), id);
    }

    /**
     * 查询全部分组
     *
     * @return 用户所在机构的全部分组
     */

    public List<UserDept> selectList() {
        Map<String, Object> params = new HashMap<>();
        return this.selectList(params);
    }

    /**
     * 查询全部分组
     *
     * @return 用户所在机构的全部分组
     */

    public List<UserDept> selectList(Map<String, Object> params) {
        params.put("orgId", userContext.getOrgId());
        return userDeptDao.selectList(params);
    }


    /**
     * a是不是b的直属下级
     *
     * @param a 用户分组a
     * @param b 用户分组b
     * @return bool
     */

    public boolean isUnderling(UserDept a, UserDept b) {
        if (a.getPath().length() >= b.getPath().length()) {
            return false;
        } else {
            return a.getPath().startsWith(b.getPath());
        }
    }


    /**
     * a是不是b的直属上级
     *
     * @param a 用户分组a
     * @param b 用户分组b
     * @return bool
     */

    public boolean isSuperior(UserDept a, UserDept b) {
        if (a.getPath().length() <= b.getPath().length()) {
            return false;
        } else {
            return a.getPath().startsWith(b.getPath());
        }
    }

    /**
     * 查询分组的角色
     *
     * @param groupId 部门ID
     * @return pojo
     */

    public Role queryRoleByGroupId(String groupId) {
        UserDept group = userDeptDao.selectById(userContext.getOrgId(), groupId);
        return roleService.queryById(group.getRoleId());
    }


    // authority ------------------------------------------------------------------------------------------

    /**
     * 查询父节点
     *
     * @return list
     */
    public UserDept queryParent() {
        return userDeptDao.selectById(userContext.getOrgId(), userContext.getUserDeptPid());
    }


    /**
     * 查询列表
     *
     * @return list
     */
    public List<UserDept> queryFully() {
        return userDeptDao.selectFully(userContext.getOrgId());
    }

    /**
     * 查询当前用户的直属上级
     *
     * @return user-list
     */
    public List<UserDept> queryAbove() {
        return userDeptDao.selectAbove(userContext.getOrgId(), userContext.getUserDept().getPath());
    }

    /**
     * 查询当前用户的平级和下级
     *
     * @return user-list
     */
    public List<UserDept> queryNode() {
        return userDeptDao.selectNode(userContext.getOrgId(), userContext.getUserDept().getPath());
    }


    /**
     * 查询当前用户的平级和下级
     *
     * @return user-list
     */
    public Set<String> queryNodeIds() {
        return userDeptDao.selectNodeIds(userContext.getOrgId(), userContext.getUserDept().getPath());
    }

    /**
     * 查询列表 - 下级
     *
     * @return user-list
     */
    public List<UserDept> queryChildren() {
        UserDept dept = userContext.getUserDept();
        return userDeptDao.selectChildren(dept.getOrgId(), dept.getPid());
    }

    /**
     * 查询列表 - 下级
     *
     * @return user-list
     */
    public Set<String> queryChildrenIds() {
        UserDept dept = userContext.getUserDept();
        return userDeptDao.selectChildrenIds(dept.getOrgId(), dept.getPid());
    }

    /**
     * 查询列表 - 子孙
     *
     * @return user-list
     */
    public List<UserDept> queryDescendant() {
        UserDept dept = userContext.getUserDept();
        return userDeptDao.selectDescendant(dept.getOrgId(), dept.getPath());
    }

    /**
     * 查询列表 - 子孙
     *
     * @return user-list
     */
    public Set<String> queryDescendantIds() {
        UserDept dept = userContext.getUserDept();
        return userDeptDao.selectDescendantIds(dept.getOrgId(), dept.getPath());
    }

    /**
     * 查询列表 - 同胞
     *
     * @return user-list
     */
    public List<UserDept> querySibling() {
        UserDept dept = userContext.getUserDept();
        return userDeptDao.selectChildren(dept.getOrgId(), dept.getPid());
    }


    /**
     * 查询列表 - 同胞
     *
     * @return user-list
     */
    public Set<String> querySiblingIds() {
        UserDept dept = userContext.getUserDept();
        return userDeptDao.selectChildrenIds(dept.getOrgId(), dept.getPid());
    }
}
